// Copyright (C) ZHENG Zhong <heavyzheng nospam-at gmail D0T com>
// http://www.zhengzhong.net/
//
// $Id: parse_by_sax.hpp 318 2009-03-02 14:03:21Z heavyzheng $
//

#ifndef ZZHENG_EXAMPLE_PARSE_BY_SAX_HPP_20090126__
#define ZZHENG_EXAMPLE_PARSE_BY_SAX_HPP_20090126__

#include <zzheng/xml/sax.hpp>

#include <cassert>
#include <exception>
#include <string>
#include <iostream>

namespace zzheng {
namespace example {

    class dummy_handler: public xml::sax::content_handler, public xml::sax::error_handler {

    public:

        explicit dummy_handler(): level_(0), warnings_(0), errors_(0), fatals_(0) {
            // Do nothing.
        }

        // Use auto-generated copy constructor.
        // Use auto-generated copy assignment.
        // Use auto-generated destructor.

        void begin_doc() {
            std::cout << "begin_doc(): level=" << level_ << std::endl;
        }

        void end_doc() {
            std::cout << "end_doc(): level=" << level_ << std::endl
                      << "           warnings=" << warnings_ << std::endl
                      << "           errors=" << errors_ << std::endl
                      << "           fatals=" << fatals_ << std::endl;
        }

        void begin_ns(const std::string& prefix, const std::string& uri) {
            std::cout << "begin_ns(): " << prefix << "=" << uri << std::endl;
        }

        void end_ns(const std::string& prefix) {
            std::cout << "end_ns(): " << prefix << std::endl;
        }

        void begin_elem(const std::string& name,
                        const std::string& uri,
                        const std::string& qname,
                        const xml::sax::attribute_list& attrs) {
            std::cout << "begin_elem(): " << name
                      << " (xmlns='" << uri << "', qname='" << qname << "')" << std::endl;
            typedef xml::sax::attribute_list::const_iterator const_iterator;
            for (const_iterator i = attrs.begin(); i != attrs.end(); ++i) {
                std::cout << "              "
                          << i->qname() << "=" << i->value
                          << " (xmlns='" << i->uri << "')" << std::endl;
            }
            ++level_;
        }

        void end_elem(const std::string& name, const std::string& uri, const std::string& qname) {
            std::cout << "end_elem(): " << name
                      << " (xmlns='" << uri << "', qname='" << qname << "')" << std::endl;
            --level_;
        }

        void characters(const char* chars, xml::sax::size_type start, xml::sax::size_type length) {
            std::cout << "characters(): ";
            for (xml::sax::size_type i = start; i < start + length; ++i) {
                std::cout << chars[i];
            }
            std::cout << std::endl;
        }

        void ignorable_whitespace(const char* chars,
                                  xml::sax::size_type start,
                                  xml::sax::size_type length) {
            std::cout << "ignorable_whitespace(): " << length << std::endl;
            chars, start;
        }

        void comment(const char* chars,
                     xml::sax::size_type start,
                     xml::sax::size_type length) {
            std::cout << "comment(): ";
            for (xml::sax::size_type i = 0; i < start + length; ++i) {
                std::cout << chars[i];
            }
            std::cout << std::endl;
        }

        void warning(const xml::sax::error_info& info) {
            std::cout << "warning(): " << info.str() << std::endl;
            ++warnings_;
        }

        void error(const xml::sax::error_info& info) {
            std::cout << "error(): " << info.str() << std::endl;
            ++errors_;
        }

        void fatal(const xml::sax::error_info& info) {
            std::cout << "fatal(): " << info.str() << std::endl;
            ++fatals_;
        }

    private:

        int level_;
        int warnings_;
        int errors_;
        int fatals_;

    }; // class dummy_handler

    ////////////////////////////////////////////////////////////////////////////////////////////////

    int parse_by_sax(const char* xml_str) {
        try {
            dummy_handler handler;
            xml::sax::parser parser;
            parser.set_content_handler(&handler);
            parser.set_error_handler(&handler);
            parser.parse_string(xml_str);
            return 0;
        } catch (const xml::sax::sax_error& ex) {
            std::cerr << "dom_error: " << ex.what() << std::endl;
            return 1;
        } catch (const std::exception& ex) {
            std::cerr << "std::exception: " << ex.what() << std::endl;
            return 1;
        } catch (...) {
            std::cerr << "unknown error." << std::endl;
            return 1;
        }
    }


} // namespace zzheng::example
} // namespace zzheng

#endif // ZZHENG_EXAMPLE_PARSE_BY_SAX_HPP_20090126__




